﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Rung.Soft.Jx3Tookit.Addon.AutoPress.Business;
using Rung.Soft.Jx3Tookit.Addon.AutoPress.Utility;

namespace Rung.Soft.Jx3Tookit.Addon.AutoPressAddon
{
    public partial class MainUC : UserControl
    {
        IntPtr jxHWnd;
        private SkillJober sJober;
        private MethodInvoker hookWorkInvoker;
        private MethodInvoker jobOnStartInvoker;
        private MethodInvoker jobOnFinishInvoker;
        private MethodInvoker taskOnStartInvoker;
        private MethodInvoker taskOnFinishInvoker;
        //private const string JX3_CAPTION = "剑侠情缘网络版叁";
        private const string JX3_CAPTION = "无标题 - 记事本";
        private bool isShowTaskFinish = true;

        public MainUC()
        {
            InitializeComponent();
        }

        /// <summary> 
        /// 清理所有正在使用的资源。
        /// </summary>
        /// <param name="disposing">如果应释放托管资源，为 true；否则为 false。</param>
        protected override void Dispose(bool disposing)
        {
            if (sJober.IsBusy)
                sJober.Stop();

            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        private void MainUC_Load(object sender, EventArgs e)
        {
            this.sJober = new SkillJober();

            ddlAddKey.Items.AddRange(HotKey.GetKeys());
            ddlFireKey.Items.AddRange(HotKey.GetKeys());

            ddlAddKey.SelectedIndex = 0;
            ddlFireKey.SelectedIndex = 0;

            #region 事件注册
            // 按键钩子捕获到按键
            this.hookWorkInvoker = new MethodInvoker(() =>
            {
                this.SetInfo("捕获按键。");

                this.sJober.FireType = rbFire2.Checked ? FireType.Cycle : FireType.Sigle;
                // 循环连击模式下，第二次点击热键将停止循环。
                if (this.sJober.FireType == FireType.Cycle && this.sJober.IsBusy)
                    this.sJober.Stop();
                else
                    this.sJober.Start();
            });
            Hook.DoWork += this.hookWorkInvoker;

            this.sJober_Init();
            #endregion

            this.tsm载入已存方案_Refresh();

            this.SetInfo("启动成功。");
        }

        // 【添加按键】
        private void btnAddKey_Click(object sender, EventArgs e)
        {
            this.sJober.Tasker.Action.Add(new SkillAction((HotKey)ddlAddKey.SelectedItem));
            this.lbKeys_Refresh();
        }

        // 【添加延迟】
        private void btnAddDelay_Click(object sender, EventArgs e)
        {
            int delay = 0;
            if (int.TryParse(txbAddDelay.Text, out delay))
            {
                this.sJober.Tasker.Action.Add(new SkillAction(delay));
                this.lbKeys_Refresh();
            }
        }

        // 【开启】
        private void cbStart_CheckedChanged(object sender, EventArgs e)
        {
            if (cbStart.Checked)
            {
                jxHWnd = Win32API.FindWindow(null, JX3_CAPTION);
                //if (jxHWnd == IntPtr.Zero)
                //{
                //    this.SetInfo("未检测到客户端！");
                //    cbStart.Checked = false;
                //}
                //else
                {
                    Hook.startKillsKey = ((HotKey)ddlFireKey.SelectedItem).Key;
                    bool b = Hook.RunHook();

                    if (b)
                        this.SetInfo("开启成功。");
                    else
                    {
                        this.SetInfo("开启失败！");
                        cbStart.Checked = false;
                    }
                }
            }
            else
            {
                Hook.UnHook();
                this.sJober.Stop();
            }
        }

        // 设置
        private void btnConfig_Click(object sender, EventArgs e)
        {
            cmsConfig.Show(Control.MousePosition);
        }

        // 【按键】双击删除
        private void lbKeys_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            this.sJober.Tasker.Action.Remove((SkillAction)lbKeys.SelectedItem);
            this.lbKeys_Refresh();
        }

        private void lbKeys_DrawItem(object sender, DrawItemEventArgs e)
        {
            if (e.Index < 0) return;

            SkillAction action = lbKeys.Items[e.Index] as SkillAction;
            if (action != null)
            {
                Color vColor = e.ForeColor;

                if (action.Type == ActionType.Key)
                    vColor = Color.Blue;
                else if (action.Type == ActionType.Delay)
                    vColor = Color.Gray;

                //e.Graphics.FillRectangle(new SolidBrush(vColor), e.Bounds);
                e.Graphics.DrawString(action.ToString(), e.Font, new SolidBrush(vColor), e.Bounds);
                //e.DrawFocusRectangle();
            }
        }

        private void 载入已存方案ToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }

        private void 保存现有方案ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.sJober.Tasker.Action.Count == 0)
            {
                MessageBox.Show("没有任何动作规则。");
            }
            else
            {
                SkillJober jober = new SkillJober();
                this.sJobers_FromUI(jober);
                new ConfigForm(jober, this).Show(this);
            }
        }

        private void 清空所有方案ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ConfigForm.sJobers.Clear();
            SerializeHelper.Serialize(ConfigForm.sJobers, ConfigForm.JOBS_FILE_NAME);

            // 刷新菜单UI
            this.tsm载入已存方案_Refresh();
        }

        private void 清空运行信息ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            lbInfo.Items.Clear();
        }

        #region 【运行信息】
        private Action<ListBox, string> lbInfo_AddItem =
            new Action<ListBox, string>(
                (lbInfo, msg) =>
                {
                    lbInfo.Items.Add(msg);
                    lbInfo.SelectedIndex = lbInfo.Items.Count - 1;
                }
            );
        private void SetInfo(string msg)
        {
            msg = string.Format("[{0}:{1}]\t{2}", DateTime.Now.Minute, DateTime.Now.Second, msg);

            if (lbInfo.InvokeRequired)
            {
                lbInfo.Invoke(lbInfo_AddItem, lbInfo, msg);
                System.Threading.Thread.Sleep(10);
            }
            else
            {
                lbInfo.Items.Add(msg);
                lbInfo.SelectedIndex = lbInfo.Items.Count - 1;
            }
        }

        private Action<ListBox, string> lbInfo_AppendInfo =
            new Action<ListBox, string>(
                (lbInfo, msg) =>
                {
                    lbInfo.Items[lbInfo.Items.Count - 1] += msg;
                    lbInfo.SelectedIndex = lbInfo.Items.Count - 1;
                }
            );
        private void AppendInfo(string msg)
        {
            if (lbInfo.InvokeRequired)
            {
                if (lbInfo.IsDisposed == false)
                {
                    lbInfo.Invoke(lbInfo_AppendInfo, lbInfo, msg);
                }
            }
            else
            {
                lbInfo.Items[lbInfo.Items.Count - 1] += msg;
                lbInfo.SelectedIndex = lbInfo.Items.Count - 1;
            }
        }
        #endregion

        private void lbKeys_Refresh()
        {
            lbKeys.Items.Clear();
            foreach (var a in this.sJober.Tasker.Action)
            {
                lbKeys.Items.Add(a);
            }
        }

        internal void tsm载入已存方案_Refresh()
        {
            载入已存方案ToolStripMenuItem.DropDownItems.Clear();
            if (ConfigForm.sJobers == null || ConfigForm.sJobers.Count == 0) return;

            foreach (var j in ConfigForm.sJobers.Values)
            {
                ToolStripMenuItem joberItem = new ToolStripMenuItem(j.Name, null, (s, e) =>
                {
                    ToolStripMenuItem item = s as ToolStripMenuItem;
                    if (item != null)
                    {
                        this.sJober = ConfigForm.sJobers[item.Text];// 设置为当前的工作
                        this.sJober_Init();
                        this.sJobers_ToUI(ConfigForm.sJobers[item.Text]);// 反映到 UI 上
                    }
                });
                joberItem.DropDownItems.Add("删除", null, (s, e) =>
                {
                    ToolStripMenuItem delItem = s as ToolStripMenuItem;
                    if (delItem != null)
                    {
                        SkillJober delJober = delItem.OwnerItem.Tag as SkillJober;
                        if (delJober != null)
                        {
                            ConfigForm.sJobers.Remove(delJober.Name);
                            SerializeHelper.Serialize(ConfigForm.sJobers, ConfigForm.JOBS_FILE_NAME);
                        }
                    }

                    // 刷新菜单UI
                    this.tsm载入已存方案_Refresh();
                });

                joberItem.Tag = j;
                载入已存方案ToolStripMenuItem.DropDownItems.Add(joberItem);
            }
        }

        /// <summary>
        /// 将指定的 Jober 反映到界面UI上。
        /// </summary>
        private void sJobers_ToUI(SkillJober j)
        {
            // 触发类型
            if (j.FireType == FireType.Sigle)
                rbFire1.Checked = true;
            else
                rbFire2.Checked = true;

            // 触发按键
            foreach (var item in ddlFireKey.Items)
            {
                HotKey itemKey = (HotKey)item;
                if (itemKey.Key == j.FireKey.Key)
                    ddlFireKey.SelectedItem = item;
            }

            // 按键规则
            lbKeys.Items.Clear();
            foreach (var a in j.Tasker.Action)
            {
                lbKeys.Items.Add(a);
            }
        }
        /// <summary>
        /// 将界面UI中的 Jober 设置保存到指定的 Jober 中。
        /// </summary>
        private void sJobers_FromUI(SkillJober j)
        {
            j.FireType = rbFire2.Checked ? FireType.Cycle : FireType.Sigle;
            j.FireKey = ddlFireKey.SelectedItem as HotKey;

            j.Tasker.Action.Clear();
            foreach (var item in lbKeys.Items)
            {
                SkillAction a = item as SkillAction;

                if (a != null)
                    j.Tasker.Action.Add(a);
            }
        }

        private void sJober_Init()
        {
            // Job - Start
            this.jobOnStartInvoker = new MethodInvoker(() => { this.SetInfo("工作开始。"); });
            this.sJober.OnJobStart += this.jobOnStartInvoker.Invoke;

            // Job - Finish
            this.jobOnFinishInvoker = new MethodInvoker(() => { this.SetInfo("工作完成。"); });
            this.sJober.OnJobFinish += this.jobOnFinishInvoker.Invoke;

            // Task - Start
            this.taskOnStartInvoker = new MethodInvoker(() =>
            {
                IntPtr currHwnd = Win32API.GetForegroundWindow();
                //this.AppendInfo(string.Format("{0}-{1}", currHwnd, jxHWnd));
                if (currHwnd != jxHWnd)
                {
                    System.Threading.Thread.Sleep(10);
                    this.sJober.Tasker.Stop();
                    this.isShowTaskFinish = false;
                }
                else
                {
                    this.SetInfo("任务开始...");
                    this.isShowTaskFinish = true;
                }
            });
            this.sJober.Tasker.OnTaskStart += this.taskOnStartInvoker.Invoke;

            // Task - Finish
            this.taskOnFinishInvoker = new MethodInvoker(() => { if (isShowTaskFinish)this.AppendInfo("完成。"); });
            this.sJober.Tasker.OnTaskFinish += this.taskOnFinishInvoker.Invoke;
        }
    }
}
